package test;

import static org.junit.Assert.*;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import dsa.LinkedList;
import dsa.ListIterator;



public class BrandonRomanoTest {

	LinkedList list;
	private String a = "a";
	private String b = "b";
	private String c = "c";
	private String d = "d";
	private String e = "e";
	
	@Before
	public void setUp() throws Exception 
	{
		
		list = new LinkedList();
		list.addFirst(a);
		list.addFirst(b);
		list.addLast(c);
		list.addLast(d);
		list.addFirst(e);
		//at {e, b, a, c, d}
		
		list.removeFirst();
		//at {b, a, c, d}
		list.removeLast();
		//at {b, a, c}
		
		list.addFirst(e);
		//at {e, b, a, c}
		
	}

	@After
	public void tearDown() throws Exception {
	}

	@Test
	public void testSize()
	{
		LinkedList tempList = (LinkedList) list.clone();
		assertTrue(tempList.size() == 4);
		
		tempList.addLast(b);
		assertTrue(tempList.size() == 5);
		
		tempList.removeFirst();
		assertTrue(tempList.size() == 4);
	}
	
	@Test
	public void testGet()
	{
		//should currently be {e, b, a, c} after setup
		assertTrue(list.get(0) == e);
		assertTrue(list.get(1) == b);
		assertTrue(list.get(2) == a);
		assertTrue(list.get(3) == c);
	}
	
	@Test
	public void testIndexOf()
	{
		LinkedList tempList = (LinkedList) list.clone();
		tempList.addLast(e);
		//should currently be {e, b, a, c, e}

		assertTrue(tempList.indexOf(e) == 0);
//		assertTrue(tempList.lastIndexOf(e) == 4);
		assertTrue(tempList.indexOf(b) == 1);
//		assertTrue(tempList.lastIndexOf(b) == 1);
		
	}
	
	@Test
	public void testContains()
	{
		assertTrue(list.contains(e));
		assertTrue(list.contains(b));
		assertTrue(list.contains(a));
		assertTrue(list.contains(c));
	}
	
	@Test
	public void testGetFirstLast()
	{
		assertTrue(list.getFirst() == e);
		assertTrue(list.getLast() == c);
	}
	
	@Test
	public void testSetAndClone()
	{
		LinkedList tempList = (LinkedList) list.clone();
		tempList.set(0, d);
		assertTrue(tempList.get(0) == d);
	}
	
	@Test
	public void testToArray()
	{
		Object[] array = list.toArray();
		assertTrue(array[0].equals(e));
		assertTrue(array[1].equals(b));
		assertTrue(array[2].equals(a));
		assertTrue(array[3].equals(c));
	}
	
	@Test
	public void removeFirstLast()
	{
		assertTrue(list.removeFirst() == e);
		assertTrue(list.size() == 3);
		
		assertTrue(list.removeLast() == c);
		assertTrue(list.size() == 2);
	}

	//--------- Iterator tests
	@Test
	public void iteratorNextPrevious()
	{
		ListIterator li = list.listIterator(0);
		assertTrue(li.next() == e);
		assertTrue(li.next() == b);
		assertTrue(li.next() == a);
		assertTrue(li.next() == c);
		assertTrue(li.next() == null);
		assertTrue(li.next() == null);
		assertTrue(li.previous() == c);
		assertTrue(li.previous() == a);
		assertTrue(li.previous() == b);
		assertTrue(li.previous() == e);
		assertTrue(li.previous() == null);
		assertTrue(li.previous() == null);
		assertTrue(li.next() == e);
		
	}
	
	@Test
	public void iteratorDiffStart()
	{
		ListIterator li = list.listIterator(1);
		assertTrue(li.next() == b);
	}
	
	//also tests nextIndex/previousIndex
	@Test
	public void iteratorAddRemove()
	{
		ListIterator li = list.listIterator(0);
		assertTrue(li.next() == e);
		li.remove();
		assertTrue(li.next() == b);
		assertTrue(li.previous() == b);
		assertTrue(li.previous() == null);
		assertTrue(li.next() == b);
		li.remove();
		li.remove();//This should do nothing (REFER TO API)
		assertTrue(li.next() == a);
		assertTrue(li.next() == c);
		assertTrue(li.next() == null);
		assertTrue(li.nextIndex() == list.size()); //There is no next, should be then list size (REFER TO API)
		assertTrue(li.previous() == c);
		assertTrue(li.previous() == a);
		assertTrue(li.previous() == null);
		assertTrue(li.previousIndex() == -1); //There is no previous, should return -1 (REFER TO API)
		//List is now simply { | a,c}, where the pipe is my pointer
		//If I add something, we expect the list to look like { | Obj, a, c}.. Let's try and test.
		li.add(e);
		assertTrue(li.previous() == e);
		//List now looks like { e, | a, c }
		//going to add one more and traverse through the list one last time
		li.add(b);
		assertTrue(li.previous() == b);
		//assertTrue(li.previous() == e);
		assertTrue(li.previous() == null);
		//Now going to check through the whole list, should be {b, e, a, c}
		assertTrue(li.next() == b);
		assertTrue(li.next() == e);
		assertTrue(li.next() == a);
		assertTrue(li.next() == c);
		assertTrue(li.next() == null);
	}
	
	@Test
	public void hasNextPrevious()
	{
		ListIterator li = list.listIterator(0);
		assertTrue(li.hasNext());
		assertTrue(li.next() == e);
		assertTrue(li.hasNext());
		assertTrue(li.next() == b);
		assertTrue(li.hasNext());
		assertTrue(li.next() == a);
		assertTrue(li.hasNext());
		assertTrue(li.next() == c);
		assertTrue(!li.hasNext());
		assertTrue(li.next() == null);
		
		assertTrue(li.hasPrevious());
		assertTrue(li.previous() == c);
		assertTrue(li.hasPrevious());
		assertTrue(li.previous() == a);
		assertTrue(li.hasPrevious());
		assertTrue(li.previous() == b);
		assertTrue(li.hasPrevious());
		assertTrue(li.previous() == e);
		assertTrue(!li.hasPrevious());
		assertTrue(li.previous() == null);
	}
	
	@Test
	public void testSet()
	{
		ListIterator li = list.listIterator(0);
		li.next();
		li.set(c);
		assertTrue(li.previous() == c);
	}
	
}
